//
// Created by suzhen on 2019-03-29.
//

#pragma once

#include <vector>

#include "qconf.h"

namespace qio {

class Buffer {
 public:
  using DataType = std::vector<char>;

  virtual ~Buffer() QIO_NOEXCEPT = default;

  // 读写

  virtual void Write(const char *data, std::size_t n) QIO_NOEXCEPT = 0;

  virtual void Write(const DataType &data) QIO_NOEXCEPT = 0;

  virtual DataType Read(std::size_t n) QIO_NOEXCEPT = 0;

  // 从头部移除 n 个元素
  virtual void Pop(std::size_t n) QIO_NOEXCEPT = 0;

  // 观察数据,不会修改 buffer , offset 为数据识别的偏移量

  virtual DataType Peek(int offset, std::size_t n) const QIO_NOEXCEPT = 0;

  virtual std::int8_t PeekInt8(int offset) const QIO_NOEXCEPT = 0;

  virtual std::uint8_t PeekUInt8(int offset) const QIO_NOEXCEPT = 0;

  virtual std::int16_t PeekInt16(int offset) const QIO_NOEXCEPT = 0;

  virtual std::uint16_t PeekUInt16(int offset) const QIO_NOEXCEPT = 0;

  virtual std::int32_t PeekInt32(int offset) const QIO_NOEXCEPT = 0;

  virtual std::uint32_t PeekUInt32(int offset) const QIO_NOEXCEPT = 0;

  inline std::int8_t PeekInt8() const QIO_NOEXCEPT { return PeekInt8(0); }

  inline std::uint8_t PeekUInt8() const QIO_NOEXCEPT { return PeekUInt8(0); }

  inline std::int16_t PeekInt16() const QIO_NOEXCEPT { return PeekInt16(0); }

  inline std::uint16_t PeekUInt16() const QIO_NOEXCEPT { return PeekUInt16(0); }

  inline std::int32_t PeekInt32() const QIO_NOEXCEPT { return PeekInt32(0); }

  inline std::uint32_t PeekUInt32() const QIO_NOEXCEPT { return PeekUInt32(0); }

  // 从 buffer 起始位置读取数据,被读取的数据会被移除,

  virtual std::int8_t ReadInt8() QIO_NOEXCEPT = 0;

  virtual std::uint8_t ReadUInt8() QIO_NOEXCEPT = 0;

  virtual std::int16_t ReadInt16() QIO_NOEXCEPT = 0;

  virtual std::uint16_t ReadUInt16() QIO_NOEXCEPT = 0;

  virtual std::int32_t ReadInt32() QIO_NOEXCEPT = 0;

  virtual std::uint32_t ReadUInt32() QIO_NOEXCEPT = 0;

  virtual DataType ReadAll() QIO_NOEXCEPT = 0;

  // 写入数据,追加到 buffer 的最后

  virtual void WriteInt8(std::int8_t) QIO_NOEXCEPT = 0;

  virtual void WriteUInt8(std::uint8_t) QIO_NOEXCEPT = 0;

  virtual void WriteInt16(std::int16_t) QIO_NOEXCEPT = 0;

  virtual void WriteUInt16(std::uint16_t) QIO_NOEXCEPT = 0;

  virtual void WriteInt32(std::int32_t) QIO_NOEXCEPT = 0;

  virtual void WriteUInt32(std::uint32_t) QIO_NOEXCEPT = 0;

  // 获取可读数据长度
  virtual std::size_t GetReadableLength() const QIO_NOEXCEPT = 0;
};

using UniqueBuffer = std::unique_ptr<Buffer>;
}  // namespace qio
